#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "area.h"
#include "sqlite3.h"

/*********************| marcos |*********************/
#define AREA_DB_FILE		"area.db"

/*********************| static data |*********************/
static sqlite3 *		area_db = NULL;

/*********************| extern data |*********************/
 area_list_p			provinces;


/*********************| static funcs |*********************/
#ifdef __cplusplus
extern "C" {
#endif

static int area_cb(void* list, int argc, char**
		argv, char** colName)
{
	area_list_p p = (area_list_p)list;
	p->area[p->size].id = atoi(argv[0]);
	memset(&p->area[p->size].name, 0, sizeof(p->area[p->size].name));
	strcpy(p->area[p->size].name, argv[1]);
	++p->size;
	
	return 0;
}
static int count_cb(void* count, int argc, char**
		argv, char** colName)
{
	int* size = (int*)count;
	*size = atoi(argv[0]);
	return 0;
}

static int area_info_cb(void* info, int argc, char**
		argv, char** colName)
{
	area_info_p p = (area_info_p)info;
	char* p_str = NULL;
	switch(p->id) {
	case 0:
		p->country = (char*)malloc(strlen(argv[0]) + 1);	
		p_str = p->country;
		break;
	case 1:
		p->city = (char*)malloc(strlen(argv[0]) + 1);	
		p_str = p->city;
		break;
	case 2:
		p->pro = (char*)malloc(strlen(argv[0]) + 1);	
		p_str = p->pro;
		break;
	};
	strcpy(p_str, argv[0]);
	p_str[strlen(argv[0])] = 0;
	--p->id;
	return 0;
}

static int unique_province(const int id)
{
	switch (id) {
	case 110000:
	case 120000:
	case 310000:
	case 500000:
	case 710000:
	case 810000:
	case 820000:
		return 1;
	};
	return 0;
}

/*********************| extern funcs |*********************/
int area_lv(const size_t id)
{
	if (id < 110000 || id > 820600) {
		return -1;
	}
	if (unique_province(id)) {
		return 2;
	}
	/* 其他省级行政单位判断 */
	int tmp = id % 10000;
	if (!tmp) {
		return 2;
	}
	/* 市级行政单位 */
	tmp = id % 100;
	if (!tmp) {
		return 1;
	} 
	return 0;
}

int init_area_db(const char* path)
{
	if (area_db) {
		return 0;
	} else {
		int ret = sqlite3_open(path, &area_db);
		if (ret || !area_db) {
			goto do_err;
		}
		provinces = init_area_list(PROVINCE_CNT);
		if (!provinces) {
			goto do_err;
		}
		const char* sql = "select id,name from province;";
		ret = sqlite3_exec(area_db, sql, area_cb, provinces, NULL);
		if (ret != SQLITE_OK) {
			goto do_err;
		}
		return 0;
do_err:
		close_area_db();
		return -1;
	}
}

int sub_area_lv(const size_t id)
{
	int ret = area_lv(id);
	return (unique_province(id) ? 1 : ret);
}

area_list_p init_area_list(const int size)
{
	if (size <=0 ) {
		return NULL;
	}
	area_list_p ret = (area_list_p)malloc(sizeof(area_list_t));
	if (ret) {
		ret->area = (area_p)malloc(sizeof(area_t) * size);
		ret->size = 0;
	}
	return ret;
}

area_list_p init_sub_area_list(const size_t father_id)
{
	int ret = sub_area_lv(father_id);
	if (ret <= 0) {
		return NULL;
	}
	const int tmp = area_lv(father_id);
	char sql[128] = {0};
	char count_sql[128] = {0};
	switch (tmp) {
	case 1:
		sprintf(sql, "select id,name from area where id like '%d__' and id != '%d';", father_id / 100, father_id);
		sprintf(count_sql, "select count(id) from area where id like '%d__' and id != '%d';", father_id / 100, father_id);
		break;
	case 2:
		if (1 == ret) {
			sprintf(sql, "select id,name from area where id like '%d____';", father_id / 10000);
			sprintf(count_sql, "select count(id) from area where id like '%d____';", father_id / 10000);
		} else {
			sprintf(sql, "select id,name from area where id like '%d__00';", father_id / 10000);
			sprintf(count_sql, "select count(id) from area where id like '%d__00';", father_id / 10000);
		}
		break;
	};
	sqlite3_stmt* stmt = NULL;
	sqlite3_prepare(area_db, count_sql, -1, &stmt, NULL);
	sqlite3_step(stmt);
	int size = sqlite3_column_int(stmt, 0);
	sqlite3_finalize(stmt);
	area_list_p p = init_area_list(size);
	ret = sqlite3_exec(area_db, sql, area_cb, p, NULL);
	if (ret != SQLITE_OK) {
		free_area_list(p);
	}
	return p;
}

void free_area_list(area_list_p list)
{
	if (list) {
		free(list->area);
		free(list);
		list = NULL;
	}
}

area_info_p init_area_info(const size_t id)
{
	int ret = area_lv(id);
	if (ret < 0) {
		return NULL;
	}
	area_info_p tmp = (area_info_p)malloc(sizeof(area_info_t));
	memset(tmp, 0, sizeof(area_info_t));
	char sql[128] = {0};

	tmp->id = 2;
	switch (area_lv(id)) {
	case 0:
		sprintf(sql, "select name from province where id='%d0000';", id / 10000);
		sqlite3_exec(area_db, sql, area_info_cb, tmp, NULL);
		/* 特别省份的县级单位当做市级单位 */
		if (unique_province(id / 10000 * 10000)) {
			memset(sql, 0, sizeof(sql));
			sprintf(sql, "select name from area where id='%d';", id);
			sqlite3_exec(area_db, sql, area_info_cb, tmp, NULL);
		} else {
			memset(sql, 0, sizeof(sql));
			sprintf(sql, "select name from area where id='%d00';", id / 100);
			sqlite3_exec(area_db, sql, area_info_cb, tmp, NULL);
			memset(sql, 0, sizeof(sql));
			sprintf(sql, "select name from area where id='%d';", id);
			sqlite3_exec(area_db, sql, area_info_cb, tmp, NULL);
		}
		break;
	case 1:
		sprintf(sql, "select name from province where id='%d0000';", id / 10000);
		sqlite3_exec(area_db, sql, area_info_cb, tmp, NULL);
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "select name from area where id='%d';", id);
		sqlite3_exec(area_db, sql, area_info_cb, tmp, NULL);
		break;
	case 2:
		sprintf(sql, "select name from province where id='%d';", id);
		sqlite3_exec(area_db, sql, area_info_cb, tmp, NULL);
		break;
	};
	tmp->id = id;
	return tmp;
}

void free_area_info(area_info_p info)
{
	if (info) {
		free(info->pro);
		free(info->city);
		free(info->country);
		info = NULL;
	}
}

void close_area_db()
{
	free_area_list(provinces);
	if (area_db) {
		sqlite3_close(area_db);
		area_db = NULL;
	}
}
#ifdef __cplusplus
};
#endif
